#ifndef CMVVISION_H
#define CMVVISION_H

#include <vector>
#include "cmvutils.h"

namespace cmv {

static const int COLOR_LEVELS = 256;
static const int MAX_COLORS = 32; // 32位存储，所以最多只能32种颜色
static const int MAX_REGIONS = 100000;
static const int MIN_AREA_SIZE = 20; // 每个区域的最小尺寸
static const int RBITS = 6; // 基数排序中的位数
static const int RADIX = (1 << RBITS); // 基数排序中的基数
static const int RMASK = RADIX - 1; // 基数排序中的掩码

/**
 * @brief 用来存储像素点的坐标
 */
struct Pixel {
	int x;
	int y;
};

/**
 * @brief 由相同颜色归属且连续的像素组成的水平直线
 */
struct Run {
	unsigned color; // 一种或多种颜色
	int length;
	int parent;
};

/**
 * @brief 连通区域
 */
struct Region {
	int color; // 颜色的id
	int area;  // 占据像素点数目
	int x1, y1, x2, y2; // 边框坐标
	float cen_x, cen_y; // 中心点坐标
	int sum_x, sum_y;
	Region *next; // 用于每种颜色对应的区域列表
};

class Vision
{
public:
	Vision()
		: m_width(0),
		  m_height(0),
		  m_map(NULL),
		  m_pixels(NULL),
		  m_runs(NULL),
		  m_numRuns(0),
		  m_numRegions(0)
	{
	}
	~Vision()
	{
		if (m_map) {
			delete []m_map;
		}
		if (m_pixels) {
			delete []m_pixels;
		}
		if (m_runs) {
			delete []m_runs;
		}
	}

	void initialize(const std::vector<Color> &colors, int width, int height);
	void classifyFrame(const unsigned char *image);
	void classifyFrame(const unsigned char *image, unsigned color, const Pixel *&pixels, int &numPixels);
	void classifyFrame(const unsigned char *image, int robot_pix_x, int robot_pix_y, int r_big, int r_small, unsigned color,
		const Pixel *&pixels, int &numPixels);
	void processFrame(const unsigned char *image);
	/**
	 * @brief 获取某像素点是不是属于某种颜色
	 *
	 * @param pixel 像素点的下标
	 * @param color 颜色的序号（0~31）
	 *
	 * @return true or false
	 */
	bool isColor(int pixel, unsigned color) const
	{
		return (m_map[pixel] & (1 << color)) ? true : false;
	}
	/**
	 * @brief 返回某种颜色对应的区域的个数
	 */
	int numRegions(int color_id)
	{
		if (color_id < 0 || color_id >= MAX_COLORS) {
			return 0;
		}
		return m_regionCount[color_id];
	}
	/**
	 * @brief 返回某种颜色对应的区域列表
	 */
	Region* getRegions(int color_id)
	{
		if (color_id < 0 || color_id >= MAX_COLORS) {
			return NULL;
		}
		return m_regionList[color_id];
	}
	void testClassify(const unsigned char *image, unsigned char *data);
	void testProcess(const unsigned char *image, unsigned char *data,
		const float *depth = 0, std::vector<Point> *points = 0);

private:
	void initThreshold();
	void encodeRuns();
	void connectComponects();
	void extractRegions();
	int separateRegions();
	void sortRegions(int max_area);
	void mergeRegions();
	Region* sortRegionListByArea(Region *list, int passes);
	int mergeRegions(Region *p, int num, double density_thresh);

	std::vector<Color> m_colors; // 配置文件中的颜色信息
	int m_width, m_height;
	unsigned m_yClass[COLOR_LEVELS]; // 用来存储y的域值信息
	unsigned m_uClass[COLOR_LEVELS]; // 用来存储u的域值信息
	unsigned m_vClass[COLOR_LEVELS]; // 用来存储v的域值信息
	unsigned *m_map; // 每个像素是否符合每种颜色的域值
	Pixel *m_pixels; // 用来保存像素点的坐标（如所有白色点的坐标）
	Run *m_runs;
	int m_numRuns; // run的个数
	Region m_regions[MAX_REGIONS]; // 连通区域
	int m_numRegions; // 连通区域的个数
	Region *m_regionList[MAX_COLORS]; // 每种颜色对应的区域列表
	int m_regionCount[MAX_COLORS]; // 每种颜色对应的区域数目
};

}

#endif // end CMVVISION_H
